#pragma once

template<typename T>
class unique_ptr {
public:
	unique_ptr()noexcept{}
	unique_ptr(T* Ptr) :_Ptr(Ptr) {}
	unique_ptr(unique_ptr&& right)noexcept {
		swap(right._Ptr, _Ptr);
	}
	unique_ptr& operator=(unique_ptr&& right) {
		if (this == &right) return *this;
		deconstruct();
		_Ptr = right._Ptr;
		right._Ptr = nullptr;
		return *this;
	}

	~unique_ptr() {
		deconstruct();
	}

	T& operator*() {
		return *_Ptr;
	}

	T* operator->() {
		return _Ptr;
	}

	T* get() {
		return _Ptr;
	}
	T* release() {
		T* old = nullptr;
		swap(_Ptr, old);
		return old;
	}

	void reset(T* Ptr = nullptr) {
		deconstruct();
		_Ptr = Ptr;
	}

private:
	unique_ptr(const unique_ptr&) = delete;
	unique_ptr& operator=(const unique_ptr&) = delete;

	void deconstruct() {
		if (_Ptr != nullptr) {
			delete _Ptr;
			_Ptr = nullptr;
		}
	}
	T* _Ptr{nullptr};
};
